package chess

import (
	"errors"
	"fmt"
)

//TODO:移动不能到它本身

type MoveChess interface {
	MoveTo(point Point) (msg string, err error)
}

func (c *Chariot) MoveTo(point Point) (msg string, err error) {
	if !point.withinRange() {
		return "", errors.New(OutOfRange)
	}
	if !c.AtARowORALine(point) {
		return "", errors.New(IllegalMove)
	}
	up, down := c.RowPiece()
	left, right := c.LinePiece()
	//当向下移动
	if c.Line < point.Line {
		//在一列向下最近的一个到不了
		if down[0].Point.Line < point.Line {
			return "", errors.New(IllegalMove)
		}
		//吃了
		if down[0].Point.Line == point.Line && down[0].Color != c.Color {
			return c.eat(down[0])
		}
	}
	//当向上移动
	if c.Line > point.Line {
		if up[0].Point.Line > point.Line {
			return "", errors.New("illegal move")
		}
		if up[0].Point.Line == point.Line && up[0].Color != c.Color {
			return c.eat(up[0])
		}
	}
	//当向右移动
	if c.Row < point.Row {
		if right[0].Point.Line < point.Line {
			return "", errors.New("illegal move")
		}
		if right[0].Point.Line == point.Line && right[0].Color != c.Color {
			return c.eat(right[0])
		}
	}
	//向左移动
	if c.Row > point.Row {
		if left[0].Point.Line > point.Line {
			return "", errors.New("illegal move")
		}
		if left[0].Point.Line == point.Line && left[0].Color != c.Color {
			return c.eat(left[0])
		}
	}
	c.successMove(point)
	return "success", nil
}

func (h *Horse) MoveTo(point Point) (msg string, err error) {
	if !point.withinRange() {
		return "", errors.New(OutOfRange)
	}
	if !h.CanGoIF(point) {
		return "", errors.New(IllegalMove)
	}
	if !h.illFoot(point) {
		return "", errors.New("撇脚马")
	}
	if val, ok := h.chessboard.M[point]; ok {
		if val.(*Piece).Color != h.Color {
			return h.eat(val.(*Piece))
		} else {
			return "", errors.New(IllegalMove)
		}
	}
	return h.successMove(point)
}

func (e *Elephant) MoveTo(point Point) (msg string, err error) {
	if !point.withinRange() {
		return "", errors.New("point out of range")
	}
	tempE := new(Elephant)
	tempE.Piece = new(Piece)
	tempE.Piece.Color = e.Piece.Color
	tempE.Point = point
	if !tempE.limit() {
		return "", errors.New(IllegalMove)
	}
	if !e.illFoot(point) {
		return "", errors.New("撇脚象")
	}
	if val, ok := e.chessboard.M[point]; ok && val.(*Piece).Color != e.Color {
		if val.(*Piece).Color != e.Color {
			return e.eat(val.(*Piece))
		} else {
			return "", errors.New(IllegalMove)
		}
	}
	return e.successMove(point)
}

func (g *Guard) MoveTo(point Point) (msg string, err error) {
	if !point.withinRange() {
		return "", errors.New("point out of range")
	}
	temp := new(Guard)
	temp.Piece = new(Piece)
	temp.Color = g.Color
	temp.Point = point
	if !temp.limit() {
		return "", errors.New(IllegalMove)
	}
	if val, ok := g.chessboard.M[point]; ok {
		if val.(*Piece).Color != g.Color {
			return g.eat(val.(*Piece))
		} else {
			return "", errors.New(IllegalMove)
		}
	}
	return g.successMove(point)
}

func (k *King) MoveTo(point Point) (msg string, err error) {
	if !point.withinRange() {
		return "", errors.New("point out of range")
	}
	temp := new(Guard)
	temp.Piece = new(Piece)
	temp.Color = k.Color
	temp.Point = point
	if !temp.limit() {
		return "", errors.New(IllegalMove)
	}
	if val, ok := k.chessboard.M[point]; ok {
		if val.(*Piece).Color != k.Color {
			return k.eat(val.(*Piece))
		} else {
			return "", errors.New(IllegalMove)
		}
	}
	return k.successMove(point)
}

func (c *Cannon) MoveTo(point Point) (msg string, err error) {
	if !point.withinRange() {
		return "", errors.New("point out of range")
	}
	if !c.AtARowORALine(point) {
		return "", errors.New("illegal move")
	}
	up, down := c.RowPiece()
	left, right := c.LinePiece()
	//当向下移动
	if c.Line < point.Line {
		//吃了,顺便把下一列到不了给铺垫一下
		if len(down) > 1 && down[1].Point.Line == point.Line && down[1].Color != c.Color {
			return c.eat(down[1])
		}
		//在一列向下最近的一个到不了
		if len(down) > 0 && down[0].Point.Line <= point.Line {
			return "", errors.New("illegal move")
		}
	}
	//当向上移动
	if c.Line > point.Line {
		if len(up) > 1 && up[1].Point.Line == point.Line && up[1].Color != c.Color {
			return c.eat(up[1])
		}
		if len(up) > 0 && up[0].Point.Line >= point.Line {
			return "", errors.New("illegal move")
		}

	}
	//当向右移动
	if c.Row < point.Row {
		if len(right) > 1 && right[1].Point.Line == point.Line && right[1].Color != c.Color {
			return c.eat(right[1])
		}
		if len(right) > 0 && right[0].Point.Line <= point.Line {
			return "", errors.New("illegal move")
		}
	}
	//向左移动
	if c.Row > point.Row {
		if len(left) > 1 && left[1].Point.Line == point.Line && left[1].Color != c.Color {
			return c.eat(left[1])
		}
		if left[0].Point.Line >= point.Line {
			return "", errors.New("illegal move")
		}

	}
	return c.successMove(point)
}

func (s *Soldier) MoveTo(point Point) (msg string, err error) {
	if !point.withinRange() {
		return "", errors.New("point out of range")
	}
	if s.Color == "red" {
		if s.Line >= 6 {
			if s.Line-1 != point.Line || s.Row != point.Row {
				return "", errors.New(IllegalMove)
			}
			if val, ok := s.chessboard.M[point]; ok {
				if val.(*Piece).Color != s.Color {
					return s.eat(val.(*Piece))
				} else {
					return "", errors.New(IllegalMove)
				}
			}
		} else {
			if !pointEqual(point, Point{s.Point.Line - 1, s.Point.Row}, Point{s.Point.Line, s.Point.Row + 1}, Point{s.Point.Line, s.Point.Row - 1}) {
				return "", errors.New(IllegalMove)
			}
			if val, ok := s.chessboard.M[point]; ok {
				if val.(*Piece).Color != s.Color {
					return s.eat(val.(*Piece))
				} else {
					return "", errors.New(IllegalMove)
				}
			}
		}
	}
	if s.Color == "black" {
		if s.Line <= 5 {
			if s.Line+1 != point.Line || s.Row != point.Row {
				return "", errors.New(IllegalMove)
			}
			if val, ok := s.chessboard.M[point]; ok {
				if val.(*Piece).Color != s.Color {
					return s.eat(val.(*Piece))
				} else {
					return "", errors.New(IllegalMove)
				}
			}
		} else {
			if !pointEqual(point, Point{s.Point.Line + 1, s.Point.Row}, Point{s.Point.Line, s.Point.Row + 1}, Point{s.Point.Line, s.Point.Row - 1}) {
				return "", errors.New(IllegalMove)
			}
			if val, ok := s.chessboard.M[point]; ok {
				if val.(*Piece).Color != s.Color {
					return s.eat(val.(*Piece))
				} else {
					return "", errors.New(IllegalMove)
				}
			}
		}
	}
	return s.successMove(point)
}

func (p *Piece) successMove(point Point) (msg string, err error) {
	str := fmt.Sprintf("%s move to %v", p.Name, point)
	delete(p.chessboard.M, p.Point)
	p.Point = point
	p.chessboard.M[point] = p
	return str, nil
}

func (h *Horse) CanGoIF(point Point) bool {
	if h.Row-2 == point.Row && (h.Line+1 == point.Line || h.Line-1 == point.Line) {
		return true
	}
	if h.Row-1 == point.Row && (h.Line+2 == point.Line || h.Line-2 == point.Line) {
		return true
	}
	if h.Row+2 == point.Row && (h.Line+1 == point.Line || h.Line-1 == point.Line) {
		return true
	}
	if h.Row+1 == point.Row && (h.Line+2 == point.Line || h.Line-2 == point.Line) {
		return true
	}
	return false
}

func (h *Horse) illFoot(point Point) bool {
	left, right := h.LinePiece()
	up, down := h.RowPiece()
	//撇左脚
	if len(left) != 0 && left[0].Row == h.Row-1 {
		if h.Row-2 == point.Row {
			return false
		}
	}
	//撇右脚
	if len(right) != 0 && right[0].Row == h.Row+1 {
		if h.Row+2 == point.Row {
			return false
		}
	}
	//撇上脚
	if len(up) != 0 && up[0].Line == h.Line-1 {
		if h.Line-2 == point.Line {
			return false
		}
	}
	//撇下角
	if len(down) != 0 && down[0].Line == h.Line+1 {
		if h.Line+2 == point.Line {
			return false
		}
	}
	return true
}
func (e *Elephant) illFoot(point Point) bool {
	if e.Line+1 == point.Line && e.Row+1 == point.Row {
		return false
	}
	if e.Line+1 == point.Line && e.Row-1 == point.Row {
		return false
	}
	if e.Line-1 == point.Line && e.Row+1 == point.Row {
		return false
	}
	if e.Line-1 == point.Line && e.Row-1 == point.Row {
		return false
	}
	return true
}

//straightLineNum 返回给定点到第一个障碍的可移动的上左下右的距离
//func (p *Piece) straightLineNum() (up, left, down, right int) {
//	myLine := p.Line
//	myRow := p.Row
//	for Row := 1 ; Row <= 10; Row ++ {
//		piece := p.chessboard.M[Point{Row, myLine}]
//	}
//
//}
